Workflow automation/AzureSiteRecovery-RansomwareProtection/SchedulerForRansomwareDetection.ps1 (227 lines of code) (raw):

param ( [parameter(Mandatory=$true)] [Object]$RecoveryPlanContext ) # Set the below Properties as variables in automation account. $VaultSubscriptionIdVariable = "VaultSubscriptionId" $VaultResourceGroupVariable = "VaultResourceGroup" $VaultNameVariable = "VaultName" $ChangePitVariable = "ChangePit" # Runbook name for the schedule runbook. $RunbookName = "RansomwareDetector" $SchedulerDays = 15 $IntervalInHours = 1 $SchedulerName = "RansomwareDetector" + (Get-Random) <# .SYNOPSIS Assigns the Azure policy. #> function Set-Policies-On-Subscription { Param ( [Parameter(Mandatory = $true)] [string] $definitionId, [Parameter(Mandatory = $true)] [string] $displayName, [Parameter(Mandatory = $true)] [string] $description ) Write-Host ('Prams 1st = {0} 2nd = {1} 3rd = {2}' -f $definitionId, $displayName, $description); $definition = Get-AzPolicySetDefinition -Id $definitionId $paramSet = @{ Name = $(New-Guid).Guid.substring(0,23) DisplayName = $displayName Description = $description PolicySetDefinition = $definition IdentityType = 'SystemAssigned' Location = 'centralus' Scope = $scope } # Create the Policy Assignment Write-Host ('Creating policy assignment {0} on {1}' -f $paramSet.DisplayName, $paramSet.Scope) $assignment = New-AzPolicyAssignment @paramSet -WarningAction SilentlyContinue # Create Role Assignments for the system managed identity $roles = @() ForEach ($PolicyDefinition in $definition.Properties.PolicyDefinitions){ $roles += ((Get-AzPolicyDefinition -Id $PolicyDefinition.policyDefinitionId).properties.policyRule.then.details.roleDefinitionIds -split "/")[-1] } ForEach ($role in ($roles | Get-Unique)){ Write-Host ('Creating {0} role assignment for remediation on: {1}' -f $role, $scope) New-AzRoleAssignment -Scope $scope -ObjectId $assignment.Identity.PrincipalId -RoleDefinitionId $role -ErrorAction SilentlyContinue | Out-Null } # Create Remediation Tasks Write-Host 'Creating Remediation Tasks' ForEach ($PolicyDefinition in $definition.Properties.PolicyDefinitions){ Start-AzPolicyRemediation -Name $PolicyDefinition.policyDefinitionReferenceId -PolicyAssignmentId $assignment.PolicyAssignmentId -PolicyDefinitionReferenceId $PolicyDefinition.policyDefinitionReferenceId -ResourceDiscoveryMode ReEvaluateCompliance | Out-Null } } # Check for required modules $requiredModules = 'Az.Accounts', 'Az.Resources', 'Az.Security', 'Az.PolicyInsights', 'Az.RecoveryServices' $availableModules = Get-Module -ListAvailable -Name $requiredModules $modulesToInstall = $requiredModules | where-object {$_ -notin $availableModules.Name} ForEach ($module in $modulesToInstall){ Write-Host "Installing Missing PowerShell Module: $module" -ForegroundColor Yellow Install-Module $module -force } # Recovery plan context from ASR recovery plan failover operation. $RecoveryPlanContext Write-Output "checking RecoveryPlanContext" $RecoveryPlanContextObj = "" try { $RecoveryPlanContextObj = $RecoveryPlanContext | ConvertFrom-Json } catch { $RecoveryPlanContextObj = $RecoveryPlanContext Write-Error -Message $_.Exception } Write-Output "getting VM map object" $VMMapColl = $RecoveryPlanContextObj.VmMap Write-Output $VMMapColl Write-Output "after getting VM map object" $SubscriptionId = "" $ResourceGroupName = "" $VMCollection = @() if($VMMapColl -ne $null) { $VMinfo = $VMMapColl | Get-Member | Where-Object MemberType -EQ NoteProperty | select -ExpandProperty Name #$vmMap = $RecoveryPlanContextObj.VmMap Write-Output "VMinfo: $VMinfo" foreach($VMID in $VMinfo) { $VM = $VMMapColl.$VMID Write-Output $VM if( !(($VM -eq $Null) -Or ($VM.ResourceGroupName -eq $Null) -Or ($VM.RoleName -eq $Null))) { $VM | Add-Member NoteProperty RecoveryPlanName $RecoveryPlanContextObj.RecoveryPlanName $VM | Add-Member NoteProperty FailoverType $RecoveryPlanContextObj.FailoverType $VM | Add-Member NoteProperty FailoverDirection $RecoveryPlanContextObj.FailoverDirection $VM | Add-Member NoteProperty GroupId $RecoveryPlanContextObj.GroupId $VM | Add-Member NoteProperty VMId $VMID $VM | Add-Member NoteProperty VmRg $VM.ResourceGroupName $VM | Add-Member NoteProperty VmName $VM.RoleName $VMCollection += $VM $SubscriptionId = $VM.SubscriptionId $ResourceGroupName = $VM.ResourceGroupName } } } else { Write-Output "VMMapColl Variable is Null" } $CollectionCount = $VMCollection.Count Write-Output "Collection Count: $CollectionCount" #Returning Collection Write-Output $VMCollection if ($SubscriptionId -eq "") { Write-Output "SubscriptionId not found." exit } Write-Output "SubscriptionId : $SubscriptionId" try { # Login to Azure using the managed system identity using in Automation account. Write-Output "Logging in to Azure..." Connect-AzAccount -Identity } catch { Write-Error -Message $_.Exception throw $_.Exception } # set the Azure subscription context. Get-AzContext $currentSub = Set-AzContext -Subscription $SubscriptionId $scope = "/subscriptions/$($currentSub.Subscription.Id)" $AutomationResource = Get-AzResource -ResourceType Microsoft.Automation/AutomationAccounts $AutomationInformation = $null foreach ($Automation in $AutomationResource) { $Job = Get-AzAutomationJob -ResourceGroupName $Automation.ResourceGroupName -AutomationAccountName $Automation.Name -Id $PSPrivateMetadata.JobId.Guid -ErrorAction SilentlyContinue if (!([string]::IsNullOrEmpty($Job))) { $AutomationInformation = @{} $AutomationInformation.Add("SubscriptionId",$Automation.SubscriptionId) $AutomationInformation.Add("Location",$Automation.Location) $AutomationInformation.Add("ResourceGroupName",$Job.ResourceGroupName) $AutomationInformation.Add("AutomationAccountName",$Job.AutomationAccountName) $AutomationInformation.Add("RunbookName",$Job.RunbookName) $AutomationInformation.Add("JobId",$Job.JobId.Guid) $AutomationInformation break; } } if ($AutomationInformation -eq $null) { Write-Output "Automation account not found." exit } # Get the Recovery services vault Id from the Automation account variable. $SubVariable = Get-AzAutomationVariable -AutomationAccountName $AutomationInformation.AutomationAccountName -ResourceGroupName $AutomationInformation.ResourceGroupName -Name $VaultSubscriptionIdVariable $VaultSubscriptionId = $SubVariable.value $RgVariable = Get-AzAutomationVariable -AutomationAccountName $AutomationInformation.AutomationAccountName -ResourceGroupName $AutomationInformation.ResourceGroupName -Name $VaultResourceGroupVariable $VaultResourceGroup = $RgVariable.value $VaultVariable = Get-AzAutomationVariable -AutomationAccountName $AutomationInformation.AutomationAccountName -ResourceGroupName $AutomationInformation.ResourceGroupName -Name $VaultNameVariable $VaultName = $VaultVariable.value $CpVariable = Get-AzAutomationVariable -AutomationAccountName $AutomationInformation.AutomationAccountName -ResourceGroupName $AutomationInformation.ResourceGroupName -Name $ChangePitVariable $ChangePit = $CpVariable.value if (($VaultName -eq $null) -or ($VaultName -eq "") -or ($VaultSubscriptionId -eq $null) -or ($VaultSubscriptionId -eq "") -or ($VaultResourceGroup -eq $null) -or ($VaultResourceGroup -eq "") -or ($ChangePit -eq $null) -or ($ChangePit -eq "")) { Write-Output "Either VaultSubscriptionId, VaultResourceGroup or VaultName variables not found." exit } $VaultId = "/Subscriptions/$VaultSubscriptionId/resourceGroups/$VaultResourceGroup/providers/Microsoft.RecoveryServices/vaults/$VaultName" $VaultId # Getting the RansomwareDetector runbook details. $Runbook = Get-AzAutomationRunbook -AutomationAccountName $AutomationInformation.AutomationAccountName -ResourceGroupName $AutomationInformation.ResourceGroupName -Name $RunbookName $Runbook # Creating a scheduler. $StartTime = (Get-Date).AddMinutes(10) # start after 10min, minimum time required to start. $EndTime = $StartTime.AddDays($SchedulerDays) # Number of days to keep the scheduler. $Schedule = New-AzAutomationSchedule -AutomationAccountName $AutomationInformation.AutomationAccountName -ResourceGroupName $AutomationInformation.ResourceGroupName -Name $SchedulerName -StartTime $StartTime -ExpiryTime $EndTime -HourInterval $IntervalInHours $Schedule Start-Sleep -Seconds 10 $params = @{"RecoveryPlanContext" = $RecoveryPlanContext;"VaultId" = $VaultId;"ChangePit" = $ChangePit} # Registering the runbook to scheduler. $JobSchedule = Register-AzAutomationScheduledRunbook -AutomationAccountName $AutomationInformation.AutomationAccountName -ResourceGroupName $AutomationInformation.ResourceGroupName -RunbookName $RunbookName -ScheduleName $SchedulerName -Parameters $params $JobSchedule # Running the policies needed at the Subscription level. We could run this at RG level if needed in future. $currentSub = Set-AzContext -Subscription $subscriptionId $scope = "/subscriptions/$($currentSub.Subscription.Id)" # Enable MDC on the subscription Write-Host "Enabling MDC on subscription: $subscriptionId" -ForegroundColor Yellow Register-AzResourceProvider -ProviderNamespace 'Microsoft.Security' #Ensure Microsoft Security Benchmark is assigned $benchmarkDefn = Get-AzPolicySetDefinition -Name "1f3afdf9-d0c9-4c3d-847f-89da613e70a8" if ($null -eq (Get-AzPolicyAssignment -Scope $scope -PolicyDefinitionId $benchmarkDefn.PolicySetDefinitionId) ) { Write-Host "Enabling Security benchmark on subscription: $subscriptionId" -ForegroundColor Yellow New-AzPolicyAssignment -Name 'Security Benchmark assignment' -PolicySetDefinition $benchmarkDefn } #Enable Microsoft Defender for Cloud plans for server. This enables the P2 plan when used with "-SubPlan P2" Write-Host 'Enabling MDC plan for servers' -ForegroundColor Yellow Set-AzSecurityPricing -Name "virtualmachines" -PricingTier "Standard" #If needed, update the workspace settings for the subscription #Set-AzSecurityWorkspaceSetting -Name "default" -Scope $subscriptionId -WorkspaceId "<path goes here>" #Configure Auto-provisioning settings Write-Host 'Enabling auto-provisioning settings' -ForegroundColor Yellow Set-AzSecurityAutoProvisioningSetting -Name "default" -EnableAutoProvision # This setting should enable the unified defender for endpoint integration for Windows & Linux Write-Host 'Enabling unified defender for endpoint integration' -ForegroundColor Yellow Set-AzSecuritySetting -SettingName WDATP -SettingKind DataExportSettings -Enabled $true Write-Host 'Assigning the required policies ' -ForegroundColor Yellow # Enable the MDE on the servers via policy $mdePolicyDefn = Get-AzPolicySetDefinition -Name 'e20d08c5-6d64-656d-6465-ce9e37fd0ebc' if ($null -eq (Get-AzPolicyAssignment -Scope $scope -PolicyDefinitionId $mdePolicyDefn.PolicySetDefinitionId) ) { Write-Host 'Assigning the policy to enable MDE' -ForegroundColor Yellow Set-Policies-On-Subscription $mdePolicyDefn.PolicySetDefinitionId 'Assignment for provisioning MDE' 'Default assignment in Defender for Cloud for provisioning MDE' } # Enable the Azure Monitor and Azure security agent via policy $securityAgentDefn = Get-AzPolicySetDefinition -Name 'a15f3269-2e10-458c-87a4-d5989e678a73' if($null -eq (Get-AzPolicyAssignment -Scope $scope -PolicyDefinitionId $securityAgentDefn.PolicySetDefinitionId) ) { Write-Host 'Assigning the policy to enable security agent' -ForegroundColor Yellow Set-Policies-On-Subscription $securityAgentDefn.PolicySetDefinitionId "Assignment for provisioning Security Agent" "Default assignment in Defender for Cloud for provisioning Sec Agent" } # Enable the AMA on the servers via policy # This isn't needed since the earlier policy handles this as well. #Set-Policies '/providers/Microsoft.Authorization/policySetDefinitions/362ab02d-c362-417e-a525-45805d58e21d' 'Default Defender for Cloud provisioning Azure Monitor agent' 'Default Defender for Cloud provisioning Azure Monitor agent'